home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / human interface toolbox / movablemodal / mmodal.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  24.7 KB  |  686 lines

  1. /*
  2.     File:        MModal.c
  3.  
  4.     Contains:    A small sample showing one way of implementing Movable Modal 
  5.                 dialogs in a 7.0 or later application.
  6.  
  7.                    Movable Modals are a new feature in the interface, and our current 
  8.                 System Software does not provide the same kind of 
  9.                 'automatic' support for them that a regular Alert or Modal Dialog 
  10.                     has, so you have to invest some code to make the things work.
  11.  
  12.                 It's not at all difficult once you understand the issues, 
  13.                 it basically comes down to adding one more global to your application,
  14.                 and checking that global whenever you might shuffle windows.
  15.  
  16.                 Here's a small sample app that has two non-modal windows.  Select 
  17.                 'Open MModal Dialog' from the Test Stuff menu, and a MModal dialog
  18.                 will come up.
  19.                 Following the interface guidelines, you can,
  20.                 • Move the MModal dialog around
  21.                 • Switch out to other applications, either with the Application menu
  22.                       or a click in another app's window or the Desktop
  23.                 • You CANNOT select any of the other two windows in the application
  24.  
  25.                 Try it, look at the code, you'll see how straightforward it can be.
  26.  
  27.                 And again, this is one way of doing it, not the only way.  Do what you need
  28.                 to in your application, keeping the Interface Guidelines as your goal.
  29.  
  30.     Written by: C.K. Haun    
  31.  
  32.     Copyright:    Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
  33.  
  34.                 You may incorporate this Apple sample source code into your program(s) without
  35.                 restriction. This Apple sample source code has been provided "AS IS" and the
  36.                 responsibility for its operation is yours. You are not permitted to redistribute
  37.                 this Apple sample source code as "Apple sample source code" after having made
  38.                 changes. If you're going to re-distribute the source, we require that you make
  39.                 it clear in the source that the code was descended from Apple sample source
  40.                 code, but that you've made changes.
  41.  
  42.     Change History (most recent first):
  43.                 8/9/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  44.                 
  45.  
  46. */
  47.  
  48. #include <fonts.h>
  49. #include <Desk.h>
  50. #include <diskinit.h>
  51. #include <resources.h>
  52. #include <toolutils.h>
  53. #include <GestaltEqu.h>
  54. #include <Balloons.h>
  55. #include <Sound.h>
  56. #include <TextUtils.h>
  57.  
  58. /* prototypes */
  59. void OpenMovable(void);
  60. void CloseMovable(void);
  61. void InitalizeApp(void);
  62. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  63. void DrawMain(WindowPtr drawIt);
  64. void DrawMain2(WindowPtr drawIt);
  65. void DrawMovable(WindowPtr drawIt);
  66. Boolean DoSelected(long val);
  67. void InitAEStuff(void);
  68. void DoHighLevel(EventRecord *AERecord);
  69. void DoDaCall(MenuHandle themenu, long theit);
  70. pascal     OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  71. pascal     OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  72. pascal   OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  73. pascal     OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  74. void SampleHelpDialog(void);
  75. void SetModalButtonState(Boolean gInBackground);
  76.  
  77. /* one external */
  78. extern void _DataInit();                                    /* this is the C initialization code */
  79.  
  80. enum  {
  81.     kMBarID = 128
  82. };
  83. enum  {
  84.     kAppleMenu = 128, kFileMenu, kEditMenu, kToolsMenu
  85. };
  86. enum  {
  87.     kResumeMask = 1,                                        /* bit of message field for resume vs. suspend */
  88.     kSampHelp = 129, kAboutBox = 128, kHelpString = 128, kNewItem = 1, kOpenItem, kCloseItem, kSaveItem, kSaveAsItem, kFileBlank1,
  89.         kPageSetupItem, kPrintItem, kFileBlank2, kQuitItem, kBadSystem = 130, kGenStrings = 128, kMenuToggleStrings = 129,
  90.         kCloseButton = 128, kMyModalKind = 1000, kMyDocumentKind
  91. };
  92. enum  {
  93.     kItem1 = 1
  94. };
  95. enum  {
  96.     kCloseIt = 1, kOpenIt
  97. };
  98.  
  99. /* some globals */
  100. MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gToolMenuHandle;
  101. Boolean gQuit, gInBackground;
  102. EventRecord gERecord;
  103. Point gSavedPoint;
  104. Boolean gSavedPos;
  105. AEDesc gTheAddress;
  106. ProcessSerialNumber gOurSN;
  107. short gHelpItem;
  108. /* this is our global to tell us if a movable modal is up*/
  109. Boolean gModalUp = false;
  110. unsigned long gMySleep = 30;
  111.  
  112. #pragma segment Main
  113. void main()
  114. {
  115.     WindowPtr twindow;
  116.     //UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  117.     InitalizeApp();
  118.    // UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  119.     do {
  120.         
  121.         WaitNextEvent(everyEvent, &gERecord, gMySleep, nil);
  122.         switch (gERecord.what) {
  123.             ProcPtr drawProc;
  124.             short tempKind;
  125.             case nullEvent:
  126.                 /* no nul processing in this sample */
  127.                 break;
  128.                 
  129.             case updateEvt:
  130.                 tempKind = ((WindowPeek)gERecord.message)->windowKind;
  131.                 /* Mkae sure it's my window before I jump through the refCon */
  132.                 /* Why, since DA's have they're own layer in 7.0? */
  133.                 /* BECAUSE there are other people in the universe who will */
  134.                 /* add things to your windowList.BalloonWriter, for example, */
  135.                 /* so you still need to be careful */
  136.                 if (tempKind == kMyModalKind || tempKind == kMyDocumentKind) {
  137.                     /* get the drawing proc from the refCon */
  138.                     drawProc = (ProcPtr)GetWRefCon((WindowPtr)gERecord.message);
  139.                     /* jump to it */
  140.                     drawProc((WindowPtr)gERecord.message);
  141.                 }
  142.                 break;
  143.                 
  144.             case mouseDown:
  145.                 /* first see where the hit was */
  146.                 /* When you first think about the Movable Modal issue, you may*/
  147.                 /* say to yerself "Hey!if there's a mouseDown all I have to do is*/
  148.                 /* see if it's in the portRect of the front window, and SysBeep if it isn't!" */
  149.                 /* Nah, too easy.Remember, you want a user to be able to switch out */
  150.                 /* of your application when a movable modal is up, so you still need */
  151.                 /* to call FindWindow and see if it was a hit in the desktop, other*/
  152.                 /* app window (same as desktop), or in the Help or Application menus. */
  153.                 /* So, we just check our gModalUp flag in any place where */
  154.                 /* window positions may shift, and sysbeep elsewhere */
  155.                 
  156.                 switch (FindWindow(gERecord.where, &twindow)) {
  157.                     
  158.                     case inDesk:                            /* if they hit in desk, then the process manager */
  159.                         break;                              /* will switch us out, we don't need to do anything */
  160.                         
  161.                     case inMenuBar:
  162.                         /* let Help and Application menus happen always */
  163.                         DoSelected(MenuSelect(gERecord.where));
  164.                         break;
  165.                         
  166.                     case inSysWindow:
  167.                         /* pass to the system */
  168.                         SystemClick(&gERecord, twindow);
  169.                         break;
  170.                         
  171.                     case inContent:
  172.                         /* Handle content and control clicks here */
  173.                         if (twindow != FrontWindow()) {
  174.                             if (!gModalUp) {
  175.                                 SelectWindow(twindow);      /* select the window */
  176.                                 SetPort(twindow);
  177.                             } else {
  178.                                 SysBeep(1);                 /* complain because they hit a back window with MM up */
  179.                             }
  180.                         } else {
  181.                             /* control tracking or whatever.In this simple sample I */
  182.                             /* only have one control possible, so deal with it */
  183.                             Point locPoint = gERecord.where;
  184.                             ControlHandle returnedControl;
  185.                             GlobalToLocal(&locPoint);
  186.                             if (FindControl(locPoint, twindow, &returnedControl)) {
  187.                                 if (TrackControl(returnedControl, locPoint, nil)) {
  188.                                     CloseMovable();
  189.                                 }
  190.                             }
  191.                         }
  192.                         break;
  193.                         
  194.                     case inDrag:
  195.                         if (twindow != FrontWindow() && gModalUp) {
  196.                             /* don't do anything, can't drag a back window */
  197.                             SysBeep(1);
  198.                         } else {
  199.                             DragWindow(twindow, gERecord.where, &qd.screenBits.bounds);
  200.                         }
  201.                         break;
  202.                         
  203.                     case inGrow:
  204.                         /* Call GrowWindow here if you have a grow box */
  205.                         break;
  206.                         
  207.                     case inGoAway:
  208.                         /* Click in Close box */
  209.                         break;
  210.                 }
  211.             case mouseUp:
  212.                 /* don't care */
  213.                 break;
  214.                 /* same action for key or auto key */
  215.             case keyDown:
  216.             case autoKey:
  217.                 if (gERecord.modifiers & cmdKey)
  218.                     DoSelected(MenuKey(gERecord.message & charCodeMask));
  219.                 break;
  220.                 
  221.             case keyUp:
  222.                 /* don't care */
  223.                 break;
  224.                 
  225.             case diskEvt:
  226.                 /* I don't do anything special for disk events, this just passes them */
  227.                 /* to a function that checks for an error on the mount */
  228.                 DoDiskEvents(gERecord.message);
  229.                 break;
  230.                 
  231.             case activateEvt:
  232.                 /* not doing anything on activates */
  233.                 break;
  234.                 
  235.             case networkEvt:
  236.                 /* don't care */
  237.                 break;
  238.                 
  239.             case driverEvt:
  240.                 /* don't care */
  241.                 break;
  242.                 
  243.             case app4Evt:
  244.                 /* If we're switching layers and I have my MModal up, I want to */
  245.                 /* change the state of the control */
  246.                 switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  247.                     
  248.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  249.                         gInBackground = (gERecord.message & kResumeMask) == 0;
  250.                         /* set dim/enable on the control */
  251.                         SetModalButtonState(gInBackground);
  252.                         break;
  253.                         
  254.                 }
  255.                 break;
  256.                 
  257.                 /* This dispatches high level events (AppleEvents, for example) */
  258.                 /* to our dispatch routine.This is NEW in the event loop for */
  259.                 /* System 7 */
  260.             case kHighLevelEvent:
  261.                 DoHighLevel(&gERecord);
  262.                 break;
  263.             default:
  264.                 break;
  265.                 
  266.         }
  267.     }
  268.             while (gQuit != true);
  269. }
  270.  
  271. /* DoDaCall opens the requested DA.It's here as a seperate routine if you'd */
  272. /* like to perform some action or just know when a DA is opened in your */
  273. /* layer.Can be handy to track memory problems when a DA is opened */
  274. /* with an Option-open */
  275. void DoDaCall(MenuHandle themenu, long theit)
  276. {
  277.     long qq;
  278.        Str255 DAname;
  279.     GetMenuItemText(themenu, theit, DAname);
  280.     qq = OpenDeskAcc(DAname);
  281. }
  282.  
  283. /* end DoDaCall */
  284.  
  285. /* DoDiskEvents just checks the error code from the disk mount, */
  286. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  287. /* You can do much more here if you care about what disks are */
  288. /* in the drive */
  289. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  290. {
  291.     short hival, loval, tommy;
  292.     Point fredpoint =  {
  293.         40, 40
  294.     };
  295.     hival = HiWord(dinfo);
  296.     loval = LoWord(dinfo);
  297.     if (hival != noErr)                                     /* something happened */ {
  298.         tommy = DIBadMount(fredpoint, dinfo);
  299.     }
  300. }
  301.  
  302. /* draws my window.Pretty simple */
  303. void DrawMain(WindowPtr drawIt)
  304. {
  305.     Handle theText;
  306.     WindowPtr tempWP;
  307.     GetPort(&tempWP);
  308.     BeginUpdate(drawIt);
  309.     SetPort(drawIt);
  310.     EraseRect(&drawIt->portRect);
  311.     theText = GetResource('TEXT', 128);
  312.     if (theText) {
  313.         Rect textRect;
  314.         HLock(theText);
  315.         HUnlock(theText);
  316.         textRect = drawIt->portRect;
  317.         InsetRect(&textRect, 20, 20);
  318.         TETextBox(*theText, GetHandleSize(theText), &textRect, 0);
  319.         ReleaseResource(theText);
  320.     }
  321.     EndUpdate(drawIt);
  322.     SetPort(tempWP);
  323. }
  324. /* a second version for variety */
  325. void DrawMain2(WindowPtr drawIt)
  326. {
  327.     Handle theText;
  328.     WindowPtr tempWP;
  329.     GetPort(&tempWP);
  330.     
  331.     BeginUpdate(drawIt);
  332.     SetPort(drawIt);
  333.     EraseRect(&drawIt->portRect);
  334.     theText = GetResource('TEXT', 130);
  335.     if (theText) {
  336.         Rect textRect;
  337.         HLock(theText);
  338.         HUnlock(theText);
  339.         textRect = drawIt->portRect;
  340.         InsetRect(&textRect, 20, 20);
  341.         TETextBox(*theText, GetHandleSize(theText), &textRect, 0);
  342.         ReleaseResource(theText);
  343.     }
  344.     EndUpdate(drawIt);
  345.     SetPort(tempWP);
  346. }
  347.  
  348. /* Draws the Movable Modal window contents */
  349. void DrawMovable(WindowPtr drawIt)
  350. {
  351.     WindowPtr tempWP;
  352.     Handle theText;
  353.     BeginUpdate(drawIt);
  354.     GetPort(&tempWP);
  355.     
  356.     SetPort(drawIt);
  357.     EraseRect(&drawIt->portRect);
  358.     theText = GetResource('TEXT', 129);
  359.     if (theText) {
  360.         Rect textRect;
  361.         HLock(theText);
  362.         HUnlock(theText);
  363.         textRect = drawIt->portRect;
  364.         InsetRect(&textRect, 20, 20);
  365.         TETextBox(*theText, GetHandleSize(theText), &textRect, 0);
  366.         ReleaseResource(theText);
  367.     }
  368.     DrawControls(drawIt);
  369.     EndUpdate(drawIt);
  370.     SetPort(tempWP);
  371. }
  372.  
  373. /* my menu action taker.It returns a Boolean which I usually ignore, but it */
  374. /* mught be handy someday */
  375. Boolean DoSelected(long val)
  376. {
  377.     short loval, hival;
  378.     Boolean returnVal = false;
  379.     loval = LoWord(val);
  380.     hival = HiWord(val);
  381.     
  382.     switch (hival) {                                        /* switch off the menu number selected */
  383.         case kAppleMenu:                                    /* Apple menu */
  384.             if (loval != 1) {                               /* if this was not About, it's a DA */
  385.                 DoDaCall(gAppleMenuHandle, loval);
  386.             } else {
  387.                 Alert(kAboutBox, nil);                      /* do about box */
  388.             }
  389.             returnVal = true;
  390.             break;
  391.         case kFileMenu:                                     /* File menu */
  392.             switch (loval) {
  393.                 case kQuitItem:
  394.                     gQuit = true;                           /* onlyitem */
  395.                     returnVal = true;
  396.                     break;
  397.                 default:
  398.                     break;
  399.             }
  400.             break;
  401.             
  402.         case kEditMenu:
  403.             /* edit menu junk */
  404.             /* don't care */
  405.             break;
  406.             
  407.         case kToolsMenu:
  408.             /* add all your test stuff here */
  409.             if (gModalUp)
  410.                 CloseMovable();
  411.             else
  412.                 OpenMovable();
  413.             break;
  414.             
  415.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  416.             /* I only care about this item.If anything else is returned here, I don't know what */
  417.             /* it is, so I leave it alone.Remember, the Help Manager chapter says that */
  418.             /* Apple reserves the right to add and change things in the Help menu */
  419.             if (loval == gHelpItem)
  420.                 SampleHelpDialog();
  421.             break;
  422.             
  423.     }
  424.     HiliteMenu(0);
  425.     return(returnVal);
  426. }
  427.  
  428. /* InitAEStuff installs my appleevent handlers */
  429. void InitAEStuff(void)
  430. {    
  431.     OSErr aevtErr = noErr;
  432.     long aLong = 0;
  433.     Boolean gHasAppleEvents = false;
  434.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  435.     *   then we exit */
  436.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  437.     /* The following series of calls installs all our AppleEvent Handlers.
  438.     *   These handlers are added to the application event handler list that 
  439.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  440.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  441.     *   list of handlers and dispatch to it if there is one.
  442.     */
  443.     if (gHasAppleEvents) {
  444.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, 
  445.              NewAEEventHandlerProc(AEOpenHandler),0, false);
  446.              if (aevtErr)  ExitToShell();
  447.  
  448.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, 
  449.              NewAEEventHandlerProc(AEOpenDocHandler),0, false);
  450.              if (aevtErr)  ExitToShell();
  451.  
  452.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, 
  453.              NewAEEventHandlerProc(AEQuitHandler), 0, false);
  454.              if (aevtErr)  ExitToShell();
  455.  
  456.          aevtErr = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, 
  457.              NewAEEventHandlerProc(AEPrintHandler),0, false);
  458.              if (aevtErr)  ExitToShell();
  459.  
  460.        } 
  461.     else ExitToShell();
  462.     
  463. }
  464. /* end InitAEStuff */
  465.  
  466. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  467.  
  468.  
  469. /* easy for me to say, huh? */
  470. void DoHighLevel(EventRecord *AERecord)
  471. {
  472.     
  473.     AEProcessAppleEvent(AERecord);
  474.     
  475. }
  476.  
  477. /* end DoHighLevel */
  478.  
  479. /* This is the standard Open Application event.*/
  480. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  481. {
  482. #pragma unused (messagein,reply,refIn)
  483.     Str255 theName;
  484.     WindowPtr myWindow, secondWindow;
  485.     /* we of course don't do anything here in this simple app */
  486.     /* except open our window */
  487.     myWindow = GetNewWindow(128, nil, (WindowPtr)-1);
  488.     ((WindowPeek)myWindow)->windowKind = kMyDocumentKind;
  489.     /* install drawing proc */
  490.     SetWRefCon(myWindow, (long)DrawMain);
  491.     /* open another one, so we can demonstrate shuffling inhibiting */
  492.     secondWindow = GetNewWindow(128, nil, (WindowPtr)-1);
  493.     ((WindowPeek)secondWindow)->windowKind = kMyDocumentKind;
  494.     /* install drawing proc */
  495.     SetWRefCon(secondWindow, (long)DrawMain2);
  496.     GetIndString(theName, kGenStrings, 1);
  497.     SetWTitle(secondWindow, theName);
  498.     SelectWindow(myWindow);
  499.     SetPort(myWindow);
  500.     return(noErr);
  501.     
  502. }
  503.  
  504. /* end AEOpenHandler */
  505.  
  506. /* Open Doc, opens our documents.Remember, this can happen at application start AND */
  507. /* anytime else.If your app is up and running and the user goes to the desktop, hilites one */
  508. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  509. /* handler will get called. Which means you don't do any initialization of globals here, or */
  510. /* anything else except open then doc.*/
  511. /* SO-- Do NOT assume that you are at app start time in this */
  512. /* routine, or bad things will surely happen to you. */
  513.  
  514. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  515. {
  516. #pragma unused (messagein,refIn,reply)
  517.     /* we of course don't do anything here */
  518.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  519. }
  520.  
  521. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  522. {                                                           /* no printing handler in yet, so we'll ignore this */
  523.     /* the operation is functionally identical to the ODOC event, with the additon */
  524.     /* of calling your print routine.*/
  525. #pragma unused (messagein,refIn,reply)
  526.     /* we of course don't do anything here */
  527.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  528. }
  529.  
  530. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.*/
  531. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.*/
  532. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  533. {
  534. #pragma unused (messagein,refIn,reply)
  535.     
  536.     /* prepQuit sets the Stop flag for us.It does _NOT_ quit, you */
  537.     /* should NEVER quit from an AppleEvent handler.Calling */
  538.     /* ExitToShell here would blow things up */
  539.     gQuit = true;
  540.     return(noErr);
  541. }
  542.  
  543. /* This is my sample help dialog.Does not do anything, expand as you need */
  544. void SampleHelpDialog(void)
  545. {
  546.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  547.     short itemhit = 0;
  548.     while (itemhit != 1) {
  549.         ModalDialog(nil, &itemhit);
  550.     }
  551.     DisposeDialog(tdial);
  552. }
  553.  
  554.  
  555. /* Opens the MModal dialog. */
  556. /* Just for grins, I'm also saving and restoring it's position in*/
  557. /* a very simple way */
  558. void OpenMovable(void)
  559. {
  560.     WindowPtr temp;
  561.     Str63 theWords;
  562.     temp = GetNewWindow(129, nil, (WindowPtr)-1);
  563.     /* install drawing proc */
  564.     SetWRefCon(temp, (long)DrawMovable);
  565.     
  566.     /* set the kind to my MModalwindow */
  567.     ((WindowPeek)temp)->windowKind = kMyModalKind;
  568.     gModalUp = true;
  569.     
  570.     /* add the go away button */
  571.     GetNewControl(kCloseButton, temp);
  572.     
  573.     /* change the menu item text */
  574.     GetIndString(theWords, kMenuToggleStrings, kCloseIt);
  575.     SetMenuItemText(gToolMenuHandle, kItem1, theWords);
  576.     
  577.     if (gSavedPos) {
  578.         /* move it to the saved position */
  579.         /* move it to 0,0 to avoid any math at all */
  580.         MoveWindow(temp, 0, 0, false);
  581.         MoveWindow(temp, gSavedPoint.h, gSavedPoint.v, false);
  582.     }
  583.     ShowWindow(temp);
  584.     /* kill all the menus except the Test, Help, and App */
  585.     DisableItem(gAppleMenuHandle, 0);
  586.     DisableItem(gFileMenuHandle, 0);
  587.     DisableItem(gEditMenuHandle, 0);
  588.     DrawMenuBar();
  589.     SetPort(temp);
  590. }
  591.  
  592. void CloseMovable(void)
  593. {
  594.     Str63 theWords;
  595.     WindowPtr temp = FrontWindow();
  596.     /* the front window really should be my modal window */
  597.     /* if it isn't, I'm bailing.*/
  598.     gSavedPos = true;
  599.     gSavedPoint.h = temp->portRect.left;
  600.     gSavedPoint.v = temp->portRect.top;
  601.     LocalToGlobal(&gSavedPoint);
  602.     if (((WindowPeek)temp)->windowKind == kMyModalKind)
  603.         CloseWindow(temp);
  604.     else
  605.         gQuit = true;
  606.     
  607.     gModalUp = false;
  608.     
  609.     /* reset the menu item text */
  610.     GetIndString(theWords, kMenuToggleStrings, kOpenIt);
  611.     SetMenuItemText(gToolMenuHandle, kItem1, theWords);
  612.     /* turn our menus back on */
  613.     EnableItem(gAppleMenuHandle, 0);
  614.     EnableItem(gFileMenuHandle, 0);
  615.     EnableItem(gEditMenuHandle, 0);
  616.     DrawMenuBar();
  617. }
  618.  
  619. /* Dim the MModal button when we go into the background */
  620. void SetModalButtonState(Boolean gInBackground)
  621. {
  622.     WindowPtr theWindow = FrontWindow();
  623.     ControlHandle theControl;
  624.     short hState;
  625.     if (gModalUp) {
  626.         /* only if we exist, o' course */
  627.         if (((WindowPeek)theWindow)->windowKind == kMyModalKind) {
  628.             /* if this isn't true, then things are weird */
  629.             hState = (gInBackground ? 255 : 0);
  630.             theControl = (ControlHandle)((WindowPeek)theWindow)->controlList;
  631.             HiliteControl(theControl, hState);
  632.             
  633.         }
  634.     }
  635. }
  636.  
  637.  
  638.  
  639. #pragma segment Initialize
  640. void InitalizeApp(void)
  641. {
  642.     MenuHandle helpHandle;
  643.     Handle myMenu;
  644.     StringHandle helpString;
  645.     short count;
  646.     long vers;
  647.     MaxApplZone();
  648.     InitGraf((Ptr)&qd.thePort);
  649.     InitFonts();
  650.     InitWindows();
  651.     InitMenus();
  652.     TEInit();
  653.     InitDialogs(nil);
  654.     InitCursor();
  655.     /* Check system version */
  656.     Gestalt(gestaltSystemVersion, &vers);
  657.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  658.     if (vers < 7) {
  659.         StopAlert(kBadSystem, nil);
  660.         ExitToShell();
  661.     }
  662.     InitAEStuff();
  663.     /* set up my menu junk */
  664.     myMenu = GetNewMBar(kMBarID);
  665.     SetMenuBar(myMenu);
  666.     gAppleMenuHandle = GetMenuHandle(kAppleMenu);
  667.     gFileMenuHandle = GetMenuHandle(kFileMenu);
  668.     gEditMenuHandle = GetMenuHandle(kEditMenu);
  669.     gToolMenuHandle = GetMenuHandle(kToolsMenu);
  670.     AppendResMenu(gAppleMenuHandle, 'DRVR');
  671.     /* now install my Help menu item in the Help Manager's menu */
  672.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  673.     count = CountMItems(helpHandle);                        /* How many items are there? */
  674.     helpString = GetString(kHelpString);                    /* get my help string */
  675.     DetachResource((Handle)helpString);                             /* detach it */
  676.     HNoPurge((Handle)helpString);
  677.     MoveHHi((Handle)helpString);
  678.     HLock((Handle)helpString);
  679.     InsertMenuItem(helpHandle, *helpString, count + 1);       /* insert my item in the Help menu */
  680.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  681.     
  682.     DrawMenuBar();
  683.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  684.     
  685. }
  686.